#include "cache_manager.h"
#include "disk_io.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>

// 缓存管理器结构：负责管理内存中的页面缓存，提高数据访问效率
struct cache_manager {
    cache_entry_t* entries;        // 缓存条目数组
    uint32_t capacity;             // 缓存容量（可存储的页面数量）
    uint32_t size;                 // 当前缓存中的页面数量
    cache_replacement_policy_t policy; // 缓存替换策略
    uint32_t hits;                 // 缓存命中次数
    uint32_t misses;               // 缓存未命中次数
    char* data_directory;          // 数据文件目录
};

// 内部辅助函数声明
static int evict_page(cache_manager_t* manager);
static void update_access(cache_manager_t* manager, int index);

// 创建缓存管理器
// 参数：
//   capacity - 缓存容量（页面数量）
//   policy - 缓存替换策略
// 返回值：
//   成功返回缓存管理器指针，失败返回NULL
cache_manager_t* cache_manager_create(uint32_t capacity, cache_replacement_policy_t policy) {
    cache_manager_t* manager = malloc(sizeof(cache_manager_t));
    if (!manager) {
        return NULL;
    }

    manager->entries = malloc(capacity * sizeof(cache_entry_t));
    if (!manager->entries) {
        free(manager);
        return NULL;
    }

    // 初始化缓存条目
    for (uint32_t i = 0; i < capacity; i++) {
        manager->entries[i].page_id = UINT32_MAX;
        manager->entries[i].is_dirty = 0;
        manager->entries[i].last_access = 0;
        manager->entries[i].access_count = 0;
        memset(manager->entries[i].data, 0, PAGE_SIZE);
    }

    manager->capacity = capacity;
    manager->size = 0;
    manager->policy = policy;
    manager->hits = 0;
    manager->misses = 0;
    manager->data_directory = NULL;

    return manager;
}

// 销毁缓存管理器
void cache_manager_destroy(cache_manager_t* manager) {
    if (manager) {
        free(manager->entries);
        free(manager->data_directory);
        free(manager);
    }
}

// 设置数据目录
void cache_manager_set_data_directory(cache_manager_t* manager, const char* data_dir) {
    if (manager->data_directory) {
        free(manager->data_directory);
    }
    manager->data_directory = strdup(data_dir);
}

// 查找页面在缓存中的位置
int cache_manager_find(cache_manager_t* manager, page_id_t page_id) {
    for (uint32_t i = 0; i < manager->capacity; i++) {
        if (manager->entries[i].page_id == page_id) {
            return i;
        }
    }
    return -1;
}

// 从缓存获取页面
storage_error_t cache_manager_get(cache_manager_t* manager, page_id_t page_id, uint8_t* buffer) {
    int index = cache_manager_find(manager, page_id);

    if (index != -1) {
        // 缓存命中
        manager->hits++;
        memcpy(buffer, manager->entries[index].data, PAGE_SIZE);
        update_access(manager, index);
        return STORAGE_OK;
    }

    // 缓存未命中
    manager->misses++;

    // 从磁盘加载
    if (disk_load_page(manager->data_directory, page_id, buffer) != STORAGE_OK) {
        return STORAGE_ERROR_IO;
    }

    // 添加到缓存
    if (manager->size >= manager->capacity) {
        evict_page(manager);
    }

    // 找到空闲位置
    for (uint32_t i = 0; i < manager->capacity; i++) {
        if (manager->entries[i].page_id == UINT32_MAX) {
            manager->entries[i].page_id = page_id;
            memcpy(manager->entries[i].data, buffer, PAGE_SIZE);
            manager->entries[i].is_dirty = 0;
            manager->entries[i].last_access = (uint32_t)time(NULL);
            manager->entries[i].access_count = 1;
            manager->size++;
            break;
        }
    }

    return STORAGE_OK;
}

// 更新访问时间
static void update_access(cache_manager_t* manager, int index) {
    manager->entries[index].last_access = (uint32_t)time(NULL);
    manager->entries[index].access_count++;
}

// 驱逐页面
static int evict_page(cache_manager_t* manager) {
    int victim_index = -1;

    if (manager->policy == CACHE_LRU) {
        // LRU策略
        uint32_t oldest_access = UINT32_MAX;
        for (uint32_t i = 0; i < manager->capacity; i++) {
            if (manager->entries[i].page_id != UINT32_MAX &&
                manager->entries[i].last_access < oldest_access) {
                oldest_access = manager->entries[i].last_access;
                victim_index = i;
            }
        }
    }
    else if (manager->policy == CACHE_FIFO) {
        // FIFO策略
        uint32_t oldest_access = UINT32_MAX;
        for (uint32_t i = 0; i < manager->capacity; i++) {
            if (manager->entries[i].page_id != UINT32_MAX &&
                manager->entries[i].last_access < oldest_access) {
                oldest_access = manager->entries[i].last_access;
                victim_index = i;
            }
        }
    }

    if (victim_index != -1) {
        // 如果页面脏，则写入磁盘
        if (manager->entries[victim_index].is_dirty) {
            disk_save_page(manager->data_directory,
                manager->entries[victim_index].page_id,
                manager->entries[victim_index].data);
        }

        // 移除缓存条目
        manager->entries[victim_index].page_id = UINT32_MAX;
        manager->entries[victim_index].is_dirty = 0;
        manager->size--;
    }

    return victim_index;
}

// 获取缓存统计
uint32_t cache_manager_get_hits(cache_manager_t* manager) { return manager->hits; }
uint32_t cache_manager_get_misses(cache_manager_t* manager) { return manager->misses; }
uint32_t cache_manager_get_size(cache_manager_t* manager) { return manager->size; }
uint32_t cache_manager_get_capacity(cache_manager_t* manager) { return manager->capacity; }

// 从缓存中移除页面
storage_error_t cache_manager_remove(cache_manager_t* manager, page_id_t page_id) {
    int index = cache_manager_find(manager, page_id);
    if (index == -1) {
        return STORAGE_OK; // 页面不在缓存中
    }

    // 如果页面脏，则写入磁盘
    if (manager->entries[index].is_dirty) {
        if (disk_save_page(manager->data_directory, page_id, manager->entries[index].data) != STORAGE_OK) {
            return STORAGE_ERROR_IO;
        }
    }

    // 移除缓存条目
    manager->entries[index].page_id = UINT32_MAX;
    manager->entries[index].is_dirty = 0;
    manager->size--;

    return STORAGE_OK;
}

// 刷新指定页面到磁盘
storage_error_t cache_manager_flush(cache_manager_t* manager, page_id_t page_id) {
    int index = cache_manager_find(manager, page_id);
    if (index == -1) {
        return STORAGE_OK; // 页面不在缓存中
    }

    // 如果页面脏，写入磁盘
    if (manager->entries[index].is_dirty) {
        if (disk_save_page(manager->data_directory, page_id, manager->entries[index].data) != STORAGE_OK) {
            return STORAGE_ERROR_IO;
        }
        manager->entries[index].is_dirty = 0;
    }

    return STORAGE_OK;
}

// 刷新所有页面到磁盘
storage_error_t cache_manager_flush_all(cache_manager_t* manager) {
    for (uint32_t i = 0; i < manager->capacity; i++) {
        if (manager->entries[i].page_id != UINT32_MAX && manager->entries[i].is_dirty) {
            if (disk_save_page(manager->data_directory,
                manager->entries[i].page_id,
                manager->entries[i].data) != STORAGE_OK) {
                return STORAGE_ERROR_IO;
            }
            manager->entries[i].is_dirty = 0;
        }
    }
    return STORAGE_OK;
}